#!/usr/bin/ruby -w

#
# == Synopsis
#
# Creates a list of all packages in google-code's bollin project with links to
# svn and with descriptions.
#
# == Usage
#
# package_list.rb > Packagelist.wiki
#
# package_list.rb -h|--help
#
# == Author
#
# Torsten Werner <twerner@debian.org>
#
# == Copyright
#
# Copyright (c) 2007 Torsten Werner.
# Licensed under the terms of the General Public license (GPL).
#

# the base URL where all packages can be found
URL = 'https://bollin.googlecode.com/svn'

# the header of the generated wiki page
HEADER = <<EOT
#summary A listing of all packages in the bollin project.
#labels Featured

Do not edit this file because it is automatically created by the script
[http://bollin.googlecode.com/svn/Bollin/package_list.rb package_list.rb] and
will be overwritten!

= List of Packages =

EOT

require 'rdoc/usage'
require 'rexml/document'

# Describes one package in the svn repository.
class Package
  # Reads the first description, the homepage, the source and all binary names
  # from debian/control and raises an exception if no description or no control
  # file at all is found.
  def initialize name
    @name = name
    @description = @homepage = @source = nil
    @binaries = []
    svn_command = "(svn cat #{URL}/#{name}/trunk/debian/control || svn cat #{URL}/#{name}/trunk/debian/control) 2> /dev/null"
    IO.popen(svn_command).each_line do |line|
      case line.chomp
      when /^Description: (.*)/
        @description ||= $1
      when /^\s*Homepage: (.*)/
        @homepage = $1
      when /^Source: (.*)/
        @source = $1
      when /^Package: (.*)/
        @binaries << $1
      end
    end
    raise 'no description' if @description.nil?
  end

  # returns information about the package in wiki syntax
  def wiki_format
    output =  package_description
    output += "   * Homepage: #{@homepage}\n"              if @homepage
    output += "   * #{pts_link} - #{buildd_link}\n" +
              "   * binary packages: #{binary_links.join(' - ')}\n"
  end

  private
  # returns a formatted string of the package description
  def package_description
    " # [#{URL}/#{@name}/trunk #{@name}]\n" +
    "   * #{@description}\n"
  end

  # returns a formatted string of the PTS link
  def pts_link
    "[http://packages.qa.debian.org/#{@source} PTS]"
  end

  # returns a formatted string of the buildd link
  def buildd_link
    "[http://buildd.debian.org/#{@source} buildd]"
  end

  # returns an array of formatted strings for the binary package pages
  def binary_links
    @binaries.map { |binary| "[http://packages.debian.org/#{binary} #{binary}]" }
  end
end


# Iterates over all packages and calls the given block for each package. It
# ignores any exceptions and uses multithreading internally.
def each_package &block         # :yields: package
  IO.popen("svn ls --xml #{URL}") do |io|
    xml = REXML::Document.new(io)
    all_threads = []
    xml.elements.each('//entry[@kind="dir"]/name') do |name|
      all_threads << Thread.new(name.text) do |packagename|
	Thread.current[:package] = Package.new(packagename) rescue nil
      end
      sleep 1
    end
    all_threads.each do |thread|
      thread.join
      yield thread[:package] if thread[:package]
    end
  end
end


# putting everything together:
if ARGV.length > 0
  RDoc::usage
end
puts HEADER
each_package { |package| puts package.wiki_format }

